from __future__ import annotations

import enum
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from sqlalchemy import func
from .. import db


class UserRole(str, enum.Enum):
	admin = "admin"
	vip = "vip"
	active = "active"
	deactivate = "deactivate"


class UserStatus(str, enum.Enum):
	active = "active"
	deactivate = "deactivate"


class User(db.Model, UserMixin):
	__tablename__ = "users"

	id = db.Column(db.Integer, primary_key=True)
	username = db.Column(db.String(80), unique=True, nullable=False, index=True)
	email = db.Column(db.String(120), unique=True, nullable=False, index=True)
	password_hash = db.Column(db.String(255), nullable=False)
	role = db.Column(db.Enum(UserRole), default=UserRole.active, nullable=False)
	status = db.Column(db.Enum(UserStatus), default=UserStatus.active, nullable=False)
	is_admin = db.Column(db.Boolean, default=False, nullable=False)
	created_at = db.Column(db.DateTime, nullable=False, server_default=func.now())
	updated_at = db.Column(db.DateTime, nullable=False, server_default=func.now(), onupdate=datetime.utcnow)

	def set_password(self, password: str) -> None:
		self.password_hash = generate_password_hash(password)

	def check_password(self, password: str) -> bool:
		return check_password_hash(self.password_hash, password)

	def get_id(self):
		return str(self.id)

	@staticmethod
	def bootstrap_admin_from_env(username: str, email: str, password: str) -> "User":
		user = User(
			username=username,
			email=email,
			role=UserRole.admin,
			status=UserStatus.active,
			is_admin=True,
		)
		user.set_password(password)
		return user

	def to_dict(self) -> dict:
		return {
			"id": self.id,
			"username": self.username,
			"email": self.email,
			"role": self.role.value if self.role else None,
			"status": self.status.value if self.status else None,
			"is_admin": self.is_admin,
			"created_at": self.created_at.isoformat() if self.created_at else None,
			"updated_at": self.updated_at.isoformat() if self.updated_at else None,
		}


